home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
web
/
spiderweb
/
tools
/
excerpt
/
filesplit.web
< prev
next >
Wrap
Text File
|
1988-03-13
|
4KB
|
164 lines
@*Splitting mailing lists.
The object of the game is to split mailing lists into multiple files.
Usage is
$$\hbox{\tt filesplit prefix numbers}$$
where {\tt prefix} is the prefix of all the output file names, and
{\tt numbers} is a list of line numbers on which pieces of the file begin.
The first line of the file is considered line~1
(for compatibility with {\tt awk(1)}).
The numbers must be sorted in increasing order.
A section consists of material from one number to the next.
The material is printed in a file whose name begins with the {\tt prefix},
and which ends with a unique suffix (e.g. {\tt 00001, 00002, ...}).
If a section number is preceded by a minus sign,
the section beginning with that line number gets thrown on the floor
instead of printed.
If the prefix is |"-"|, we write all the writable sections to standard
output.
This makes it posssible to extract just pieces of a file.
@<Print usage message and exit@>=
fprintf(stderr,"Usage:\n");
fprintf(stderr,"\tfilesplit prefix numbers...\n");
exit(1);
@ @c
#include <stdio.h>
main (argc, argv)
int argc;
char ** argv;
{
char *prefix;
@<Variable declarations@>;
if (argc--<3) {
@<Print usage message and exit@>;
}
prefix = *++argv;
argc--, argv++;
@<With |argc=number count| and |argv| pointing to list, process
standard input into files@>;
exit(0);
}
@ With only one number left in the list, our job is to print from that
line to end of file.
Otherwise, we have two numbers, which we'll call |from_line| and |to_line|.
We'll track the current line with |this_line|, which will be the number of
next line schedule to be written to the output (or thrown on the floor).
We have an implicit initial {\tt -1}, i.e. we don't print the initial
segment of the file.
@<Variable dec...@>=
int from_line, to_line;
int this_line; /* the number of the next line scheduled to be
printed */
@
@<With |argc=number count| and |argv| pointing to list, process
standard input into files@>=
multi_output=1;
@<If |prefix=="-"|, make |stdout| the output file and set |multi_output=0|@>;
printing=0;
from_line=0;
this_line=1;
while (argc!=0) {
@<Read an argument into |to_line|, set |next_printing|,
check for order,
and advance |argv|@>;
@<If |printing && multi_output|,
choose a name for the output file and open it@>;
while (this_line != to_line) {
@<Copy current line to output file
(or throw out if not |printing|)
and advance |this_line|,
jumping to |finish| on end of file@>;
}
@<If |printing && multi_output|, close the output file@>;
from_line = to_line;
printing = next_printing;
}
@<If |printing && multi_output|,
choose a name for the output file and open it@>;
while (1) {
@<Copy current line to output file...@>;
}
finish:
@<Yelp if we ended prematurely@>;
@ We ended prematurely if |from_line!=to_line|.
@<Yelp...@>=
if (from_line != to_line)
fprintf(stderr,"filesplit: premature end of file\n");
@ We might as well get the details of the output files done with now.
@<Variable dec...@>=
FILE *output;
char filename[255];
int sequence_number=0;
int multi_output;
@ @<If |prefix=="-"|, make |stdout| the output file and set |multi_output=0|@>=
if (!strcmp(prefix,"-")) {
output=stdout;
multi_output=0;
}
@ @<If |printing && multi_output|, choose a name...@>=
if (printing && multi_output) {
sprintf(filename,"%s%05d", prefix, sequence_number++);
if ((output=fopen(filename,"w"))==NULL) {
@<Print an error message and exit@>;
}
}
@ @<If |printing && multi_output|, close the output file@>=
if (printing && multi_output) fclose(output);
@ Here's how the copying works
@<Copy current line to output file...@>=
while ((c=getchar())!=EOF) {
if (printing) putc(c,output);
if (c=='\n') {
this_line++;
break;
}
}
if (c==EOF) goto finish;
@ @<Variable dec...@>=char c;
@ Since we determine sign when we read the target, we save the sign to set
|printing| the next time around.
@<Variable dec...@>=int printing, next_printing;
@ Here's our argument processing:
@ @<Read an argument into |to_line|...@>=
sscanf(*argv++,"%d",&to_line); argc--;
if (to_line<0) {
to_line = - to_line;
next_printing = 0;
}
else {
next_printing=1;
}
if (to_line <= from_line) {
fprintf(stderr,"filesplit: numbers out of order\n");
exit(-1);
}
@ @<Print an error message and exit@>=
fprintf(stderr,"filesplit: I couldn't open a file or something\n");
exit(-1);
@*Index.